<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>Vue.js 组件 - 自定义事件</title>

  <script src="https://unpkg.com/vue/dist/vue.js"></script>

</head>

<body>
  <!-- 
    父组件是使用 props 传递数据给子组件，但如果子组件要把数据传递回去，就需要使用自定义事件！
    我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface)，即：
      使用 $on(eventName) 监听事件
      使用 $emit(eventName) 触发事件
    另外，父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。 
  -->
  <div id="app">

    <!-- 子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件 -->
    <div id="counter-event">
      <p>{{total}}</p>
      <!-- 监听事件 -->
      <button-counter v-on:increment='incrementTotal'></button-counter>
      <button-counter v-on:increment='incrementTotal'></button-counter>
      <br><br>

      <!-- 如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on  -->
      <a-cmp v-on:click.native="handleClick"></a-cmp>
      <br><br>

      <!-- data 必须是一个函数 -->
      <button-counter2></button-counter2>
      <button-counter2></button-counter2>
      <button-counter2></button-counter2>
      <br><br>

      <!--   
      自定义组件的 v-model
      组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件。 
        <input v-model="parentData">
      等价于：

      <input 
          :value="parentData"
          @input="parentData = $event.target.value">
      -->

      <!--  
        自定义组件 runoob-input，父组件的 num 的初始值是 100，更改子组件的值能实时更新父组件的 num 
      -->
      <ronoob-input v-model="number"></ronoob-input>
      <p>输入的数字为: {{number}}</p>
      <br><br>

      <!-- 由于 v-model 默认传的是 value，不是 checked，所以对于对于复选框或者单选框的组件时，我们需要使用 model 选项，model 选项可以指定当前的事件类型和传入的 props。 -->
      <base-checkbox v-model="lovingVue"></base-checkbox>
      <div v-show="lovingVue">
        如果选择框打勾就会显示。
      </div>
    </div>
  </div>

  <script>
    Vue.component('button-counter', {
      template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
      // data是一个函数
      // 这样的好处就是每个实例可以维护一份被返回对象的独立的拷贝，如果 data 是一个对象则会影响到其他实例
      data: function () {
        return {
          counter: 0
        }
      },
      methods: {
        incrementHandler: function () {
          console.log("run incrementHandler counter");
          this.counter += 1,
            console.log("run incrementHandler counter2");
          // 发送事件调用increment属性，这里实际是间接性的调用了incrementTotal函数
          this.$emit('increment');
        }
      }
    })

    var buttonCounter2Data = {
      count: 0
    }

    Vue.component(
      'button-counter2', {
      data: function () {
        // data 选项是一个函数，组件不相互影响 
        // data 选项是一个对象，会影响到其他实例
        return buttonCounter2Data
      },
      template: '<button v-on:click="count++">点击了{{count}} 次</button>'
    })

    Vue.component('ronoob-input', {
      template: `
        <p> <!-- 包含了名为input的事件 -->
          <input
          ref="input"
          :value="value"
          @input="$emit('input',$event.target.value)"> 
        </p>
      `,
      props: ['value'] // 名为value的prop
    })

    Vue.component('base-checkbox', {
      model: {
        prop: 'checked',
        event: 'change' // onChange事件
      },
      props: {
        checked: Boolean
      },
      template: `
        <input
          type="checkbox"
          v-bind:checked="checked"
          v-on:change="$emit('change',$event.target.checked)"
        >
      `
    })

    new Vue({
      el: "#counter-event",
      data: {
        total: 0,
        number: 100,
        lovingVue: true
      },
      components: {
        // 定义局部组件
        'a-cmp': {
          // template: '<div> 监听原生事件 </div>',
          template: '<button> 监听原生事件 </button>',
        }
      },
      methods: {
        incrementTotal: function () {
          console.log("run incrementTotal total");
          this.total += 1
          console.log("run incrementTotal total2");
        },
        handleClick: function () {
          alert("处理点击事件!!!");
        }
      }
    })


  </script>

</body>

</html>